/**
 * package for all of the controller classes to fit MVC design pattern
 */
package javamonsters.controller;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javamonsters.model.InventoryItem;
import javamonsters.model.Marketplace;
import javamonsters.model.Player;
import javamonsters.model.TradeGood;
import javamonsters.universe.application.UniverseController;
import javamonsters.view.MarketplaceView;
import javamonsters.view.SpaceTraders;

import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JList;



/**
 * MarketplaceController controls MarketplaceView, handling the actions
 * that occur on the marketplace screen
 * 
 * @author yyao36
 * @version 1.0
 */
public class MarketplaceController {
	
	/**
	 * the marketplace view for this controller
	 */
	private final MarketplaceView marketView;
	
	/**
	 * the marketplace model for this controller
	 */
	private Marketplace market;
	
	/**
	 * the main game controller
	 */
	private final SpaceTraders parent;
	
	/**
	 * the renderer for the sell list
	 */
	private DefaultListCellRenderer sellRenderer;
	
	/**
	 * the renderer for the buy list
	 */
	private DefaultListCellRenderer buyRenderer;
	
	/**
	 * Constructor for MarketplaceController which sets ActionListeners
	 * for the buttons on the View
	 * 
	 * @param marketView the MarketplaceView that the controller has access to
	 * @param parent The parent controller which is the main game controller
	 */
	public MarketplaceController(MarketplaceView marketView, SpaceTraders parent) {
		this.marketView = marketView;
		this.parent = parent;
		marketView.getToMarketButton().addActionListener(new ToMarketButtonListener());
		marketView.getToCargoButton().addActionListener(new ToCargoButtonListener());
		marketView.getBackToMapButton().addActionListener(new BackButtonListener());
		marketView.getToShipYardButton().addActionListener(
				   new ToShipYardButtonListener());
	}
	
	/**
	 * @return String representation of marketplace controller
	 */
	public String toString() {
		return "marketplace controller";
	}
	
	/**
	 * @return the controllers Marketplace model
	 */
	public Marketplace getMarket() {
		return market;
	}
	
	/**
	 * Button listener for the buy button on the Marketplace screen
	 * @author Sami
	 *
	 */
	private class ToCargoButtonListener implements ActionListener {
		/**
		 * purchases the item from the trader and updates the screen
		 * 
		 * @param e The action event that represents the press of the button
		 */
		public void actionPerformed(ActionEvent e) {
			
			@SuppressWarnings("unchecked")
			final Map.Entry<TradeGood, InventoryItem> selectedValue
				  = (Map.Entry<TradeGood, InventoryItem>)
			      marketView.getBuyList().getSelectedValue();
			if (selectedValue != null && selectedValue.getValue().getQuantity() > 0) {
				market.buy(selectedValue.getKey(), 1);
				marketView.getCreditsLabel().setText(
						market.getCharacter().getCredits().toString());
				marketView.getBuyListModel().clear();
				marketView.getSellListModel().clear();
				for (Map.Entry<TradeGood, InventoryItem> entry : 
					 market.getBuyMap().entrySet()) {
					marketView.getBuyListModel().addElement(entry);
				}
				for (Map.Entry<TradeGood, InventoryItem> entry : 
					 market.getSellMap().entrySet()) {
					marketView.getSellListModel().addElement(entry);
				}
				
				//sets cargo list in side panel to be the cargo list in marketplace panel
				final DefaultListModel model = new DefaultListModel();
				final Map<TradeGood, Integer> cargoMap = 
				      new HashMap<TradeGood, Integer>();
				for(Map.Entry<TradeGood, InventoryItem> entry : 
					market.getSellMap().entrySet()) {
					cargoMap.put(entry.getKey(), (Integer) (
							entry.getValue()).getQuantity());
				}
				for(Map.Entry<TradeGood, Integer> entry : cargoMap.entrySet()) {
					model.addElement(entry);
				}
				final JList list = parent.getUniverseController()
						.getSideView().getCargoList();

				parent.getUniverseController().getSideView().setCargoModel(model);
				list.setModel(model);
				
				//TODO: put this somewhere to make the buy list update properly
				marketView.getBuyList().updateUI();
				
			}
		
		}
		
		/**
		 * @return String representation of the to cargo button listener
		 */
		public String toString() {
			return "to cargo button listener";
		}
	}
	
	/**
	 * Button listener for the sell button on the Marketplace screen
	 * @author elahurd3
	 *
	 */
	private class ToMarketButtonListener implements ActionListener {
		/**
		 * sells the item from the trader and updates the screen
		 * 
		 * @param e The action event that represents the press of the button
		 */
		public void actionPerformed(ActionEvent e) {
			@SuppressWarnings("unchecked")
			final Map.Entry<TradeGood, InventoryItem> selectedValue = 
		    (Map.Entry<TradeGood, InventoryItem>) marketView
		    .getSellList().getSelectedValue();
			if (selectedValue != null && selectedValue.getValue().getQuantity() > 0
			    && !selectedValue.getValue().isGray()) {
				market.sell(selectedValue.getKey(), 1);
				marketView.getCreditsLabel().setText(
						market.getCharacter().getCredits().toString());
				marketView.getBuyListModel().clear();
				marketView.getSellListModel().clear();
				for (Map.Entry<TradeGood, InventoryItem> entry : 
					 market.getBuyMap().entrySet()) {
					marketView.getBuyListModel().addElement(entry);
				}
				for (Map.Entry<TradeGood, InventoryItem> entry : 
					 market.getSellMap().entrySet()) {
					marketView.getSellListModel().addElement(entry);
				}
				
				//sets cargo list in side panel to be the cargo list in marketplace panel
				final DefaultListModel model = new DefaultListModel();
				final Map<TradeGood, Integer> cargoMap = 
					  new HashMap<TradeGood, Integer>();
				for(Map.Entry<TradeGood, InventoryItem> entry : 
					market.getSellMap().entrySet()) {
					cargoMap.put(entry.getKey(), (Integer) (
							entry.getValue()).getQuantity());
				}
				for(Map.Entry<TradeGood, Integer> entry : cargoMap.entrySet()) {
					model.addElement(entry);
				}
				final JList list = parent.getUniverseController()
						.getSideView().getCargoList();
				parent.getUniverseController().getSideView().setCargoModel(model);
				list.setModel(model);
				
			}
			
		}
		
		/**
		 * @return String representation of to market button listener
		 */
		public String toString() {
			return "to market button listener";
		}
	}
	
	/**
	 * Button listener for the back button on the Marketplace screen
	 * @author yyao36
	 *
	 */
	private class BackButtonListener implements ActionListener {
		/**
		 * shows the UniverseView
		 * @param e ActionEvent that represents the press of the button
		 */
		public void actionPerformed(ActionEvent e) {
			
			final int fuel = parent.getPlayer().getShip().getFuel();
			
			final UniverseController universeController = parent.getUniverseController();
			
			universeController.getSideView()
			.getCurrentFuelLabel().setText("" + fuel);
			
			universeController.getSideView()
			.getFuelCostLabel().setText("" + 0);
			
			parent.show("Dual Universe Panel");
		}
		
		/**
		 * @return String representation of back button listener
		 */
		public String toString() {
			return "back button listener";
		}
	}
	
	/**
	 * a button listener for the ToShipYard button
	 * @author wa
	 *
	 */
	private class ToShipYardButtonListener implements ActionListener {
		
		/**
		 * @param e ActionEvent that represents the press of the button
		 */
		public void actionPerformed(ActionEvent e) {
			
			final Marketplace market = parent.getMarketplaceController().getMarket();
			
			final String currSystem = market.getParentPlanet().getName();
			
			final String techLevel = market
					.getParentPlanet().getTechLevel().toString();
			
			final String credits = market.getCharacter().getCredits().toString();
			
			final String ship = market.getCharacter().getShip().toString();
			
			final int fuel = market.getCharacter().getShip().getFuel();
			
			final int fuelToBuy = market.getCharacter().getShip()
					.getMaxFuel() - market.getCharacter().getShip().getFuel();
			
			//set all the labels in ship yard
			
			final ShipYardController shipYardController = parent.getShipYardController();
			
			shipYardController.getShipYardView()
			.getFuelSlider().setMaximum(fuelToBuy);
			
			shipYardController.getShipYardView()
			.getSystemLabel().setText(currSystem);
			
			shipYardController.getShipYardView()
			.getTechLevelLabel().setText(techLevel);
			
			shipYardController.getShipYardView()
			.getCreditsLabel().setText(credits);
			
			shipYardController.getShipYardView()
			.getCurrentShipLabel().setText(ship);
			
			shipYardController.getShipYardView()
			.getCurrentFuelLabel().setText("Current Fuel: " + fuel);
			
			parent.show("Ship Yard View");
		}
		
		/**
		 * @return String representation of to ship yard button listener
		 */
		public String toString() {
			return "to ship yard button listener";
		}
	}
	
	/**
	 * Sets the Marketplace for the controller
	 * 
	 * @param mkt the Marketplace to be set
	 */
	public void setMarket(Marketplace mkt) {
		this.market = mkt;
		//updates the labels on the MarketplaceView
		marketView.getSystemLabel().setText(market.getParentPlanet().getName());
		marketView.getCreditsLabel().setText(market.getCharacter()
				.getCredits().toString());
		marketView.getTechLevelLabel().setText(market.getParentPlanet()
				.getTechLevel().toString());
		
		market.initializeMaps();
		marketView.getBuyListModel().clear();
		marketView.getSellListModel().clear();
		
		for (Map.Entry<TradeGood,InventoryItem> entry : market.getBuyMap().entrySet()) {
			marketView.getBuyListModel().addElement(entry);
		}
	
		for (Map.Entry<TradeGood,InventoryItem> entry : market.getSellMap().entrySet()) {
			marketView.getSellListModel().addElement(entry);
			//creates ListCellRenderer for the sell list so that certain items can be grayed out
			sellRenderer = new DefaultListCellRenderer() {

				@SuppressWarnings("unchecked")
				public Component getListCellRendererComponent(
						JList list, Object value, int index,
				            boolean isSelected, boolean cellHasFocus) {
				        Component comp = super.getListCellRendererComponent(
				        		list, value, index, isSelected, cellHasFocus);
				        //sets items that are below min-use tech level to gray...toMarketButtonListener handles 
				        //not being able to sell these items
				        if(market.getParentPlanet().getTechLevel().compareTo
		        		        (((Entry<TradeGood, InventoryItem>) value)
		        		        		.getKey().getMinUseTechLvl()) < 0) {
				        	comp.setForeground(Color.gray);
				        	((Entry<TradeGood, InventoryItem>) value)
				        	.getValue().setIsGray(true);
				        }
				        
				        return this;
				    }
				};
				
			buyRenderer = new DefaultListCellRenderer() {

				@SuppressWarnings("unchecked")
				public Component getListCellRendererComponent(JList list,
						Object value, int index,
					        boolean isSelected, boolean cellHasFocus) {
					        Component comp = super.getListCellRendererComponent(
					        list, value, index, isSelected, cellHasFocus);
					        	
					        	final Player player = parent.getPlayer();
					        
					        	if(((Integer) player
					        			.getCredits().intValue()).compareTo(
					        	  (((Entry<TradeGood, InventoryItem>) value)
					        			  .getValue().getPrice().intValue())) < 0) {
					        			comp.setForeground(Color.gray);
					        			((Entry<TradeGood, InventoryItem>) value)
					        			.getValue().setIsGray(true);
					        	}
					        
					        	return this;
					    	}
			};
			
			marketView.getBuyList().setCellRenderer(buyRenderer);
			marketView.getSellList().setCellRenderer(sellRenderer);
		}
		
		
	}
	
	/**
	 * @return the market view for this controller
	 */
	public MarketplaceView getMarketView() {
		return marketView;
	}
	
	/**
	 * @return marketplace reference for this controller
	 */
	public Marketplace getMarketplace() {
		return market;
	}
	
}
